/*
 *  lib-smv: Matrix - Vector Library targeted to Structural Mechanics Problems
 *  Copyright (C) 2006-2008  St.Brcic, Lj.Zugic
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
/** @file LinEqs.h
 *  @brief Definition of class LinEqs - solution of linear algebraic equations
 *
 *  LINEAR EQUATIONS  
 *  A * x = b (and/or A * X = B)
 *
 *  Direct and iterative solutions
 *  Crout's LU decompostion
 *  Cholesky L LT decomposition
 *  Conjugate gradients (not yet)
 */ 

#ifndef _LINEQS_H
#define _LINEQS_H

#include <iostream>
#include <fstream>
#include <iomanip>
#include <cstdlib>
#include <cstdio>
#include <cmath>
#include <cassert>
#include <string>
#include "Arrays.h"
#include "iArrays.h"
#include "Crout.h"
#include "Cholesky.h"

using namespace std;
namespace smv_lib
{

//! Direct or Iterative solution
enum EQ_GROUP  {DIRECT, ITERATIVE};
enum EQ_DIRECT {CROUT, CHOLESKY};

//---------------------------------------------------------------
/**
** \brief class LinEqs - solution of linear algebraic equations
**
**  LINEAR EQUATIONS A * x = b or SYSTEMS A * X = B
**  
**  DIRECT SOLUTIONS:
**  (1) Crout's LU decomposition, for general matrices, 
**  (2) Cholesky decomposition, for symmetric posivive definite
**  (3) QR decomposition
**  (4) Tri-diagonal equations
**  ITERATIVE SOLUTIONS:
**  (5) Conjugate Gradients
**
**/
//---------------------------------------------------------------
class LinEqs
{
  private:
    //! Matrix A (square real and positive definite)
    Matrix A;
    //! Vector b (right-hand side)
    Vector b;
    //! Order of matrix A and vector b
    int N;
    //! Solution of the problem A * x = b
    Vector x;
    //! Number of right-hand side vectors (no. of eqs. with the same coefficient matrix A)
    int M;
    //! Matrix B - right hand side of equations A * X = B (B is matrix N x M)
    Matrix B;
    //! Matrix X - the solution of linear equations A * X = B (X is matrix N x M)
    Matrix X;
    ////! LU decomposition of the matrix A
    //Matrix A_LU;

    //! Direct or Iterstive solution
    EQ_GROUP EQ_Group;
    //! Direct solution: Crout or Cholesky
    EQ_DIRECT EQ_Direct;
    //! Indicator: true if matrix A is given
    bool isMatrix_A;
    //! Indicator: true if vector b is given (A*x=b)
    bool isVector_b;
    //! Indicator: true if matrix B is given (A*X=B)
    bool isMatrix_B;
    //! Indicator: true if more sistems of eqs. with the same matrix A are solved
    bool isMore;
    //! Indicator: true if direct method of solution is given
    bool isDirect;
    //! Indicator: true if the name of the problem is given
    bool isNameGiven;
    //! Indicator: true if the solution is obtained
    bool isSolved;
    //! input stream
    ifstream in;
    //! output stream
    ofstream out;
    //! Name of the problem (output file is Name + ".txt")
    string Name;

    //! Solution methods for linear equations
    //! General matrix - Crout's LU decomposition
    Crout* m_Crout;
    //! Symmetrix matrix - Cholesky decomposition
    Cholesky* m_Chol;
    //! Indicator: true if Crout LU is selected
    bool isCrout;
    //! Indicator: true if Cholesky LLT is selected
    bool isCholesky;

  public:
    //! empty (default) constructor
    LinEqs(void);
    //! constructor with coefficient matrix and a right-hand side vecctor
    LinEqs(const Matrix& AA, const Vector& bb, EQ_GROUP group = DIRECT);
    //! constructor with coefficient matrix and a right-hand side matrix
    LinEqs(const Matrix& AA, const Matrix& BB, EQ_GROUP group = DIRECT);
    //! destructor
    ~LinEqs(void);
    //------------ set and get functions (in case of a default constructor)
    //! set Matrix A
    void setMatrix_A(const Matrix& AA);
    //! set the right-hand side vector b (A * x = b)
    void setVector_b(const Vector& bb);
    //! set the right-hand side matrix B (A * X = B)
    void setMatrix_B(const Matrix& BB);
    //! set the name of the problem
    void setName(const string name);
    //! set the method of solution: default is direct method
    void setMethod(EQ_GROUP method = DIRECT);
    //! set direct method of solution: default is Crout's LU
    void setDirect(EQ_DIRECT direct = CROUT);

    //! obtain the solution
    void solveProblem();
    //! give the result for the single equation A * x = b
    Vector getSolution();
    //! get one solutions of the system of linear equations A * X = B
    Vector getSolutionNo(int i);
    //! get all solutions of the system of linear equations A * X = B
    Matrix getAllSolutions();
    //! write results to predefined file "LinEqs.txt"
    void Write();
    //! write results to file with a given name
    void WriteTo(const char* file);
    //! give the method of solution as a string
    const string giveMethod() const;
    //! give the method of direct solution as a string
    string giveDirectMethod();
    //! give the method of iterative solution as a string
    string giveIterative();

  private:
    //! direct solution of equations
    void direct();
    //! Crout's LU decomp[osition (general matrix)
    void crout();
    //! Cholesky decomposition (symmetric matrix)
    void cholesky();
    //! iterative solution of equations
    void iterative();
};

}  // end of namespace smv_lib
#endif //  _LINEQS_H

//=============================== end of file
